﻿/** 表格扩展模块 date:2020-02-29   License By http://easyweb.vip */

layui.define(["layer", "table", "laytpl", "contextMenu"], function (exports) {
    var jquery = layui.jquery;
    var layer = layui.layer;
    var table = layui.table;
    var laytpl = layui.laytpl;
    var contextMenu = layui.contextMenu;
    var device = layui.device();
    var ELEM_SEARCH = "tb-search";
    var ELEM_REFRESH = "tb-refresh";
    var ELEM_EXPORT = "tb-export";
    var m = "txField_";
    var tableX = {};

    /**
     * 合并单元格
     * @param tableId 表格的lay-filter
     * @param indexs 要合并列的索引，数组类型
     * @param fields 根据数据字段判断是否相同，为空时根据单元格的html内容判断，某一列的多行合并是根据字段或者内容合并的
     * @param isListenMerges 是否需要监听排序后重新合并，默认为true
     */
    tableX.merges = function (tableId, indexs, fields, isListenMerges) {
        if (typeof fields === "boolean") {
            isListenMerges = fields;
            fields = undefined
        }
        var $table = jquery('[lay-filter="' + tableId + '"]+.layui-table-view>.layui-table-box>.layui-table-body>table');
        var $row = $table.find(">tbody>tr");
        for (var i = 0; i < indexs.length; i++) {
            if (fields) { // 按数据字段中相同内容进行合并
                mergesFun(tableId, indexs[i], fields[i])
            } else { // 按单元格中相同html内容进行合并
                mergesFun(tableId, indexs[i])
            }
        }
        $row.find('[del="true"]').remove();
        if (isListenMerges === undefined || isListenMerges) { // 是否需要监听排序后重新合并，默认为true
            table.on("sort(" + tableId + ")", function () {
                tableX.merges(tableId, indexs, fields, false)
            })
        }

        function mergesFun(tableId, index, field) {
            var data = table.cache[tableId];
            if (data.length > 0) {
                var initContent, theSameCount = 1;
                if (field) {
                    initContent = data[0][field]
                } else {
                    initContent = $row.eq(0).find("td").eq(index).find(".layui-table-cell").html()
                }
                for (var i1 = 1; i1 < data.length; i1++) {
                    var cmpContent;
                    if (field) {
                        cmpContent = data[i1][field]
                    } else {
                        cmpContent = $row.eq(i1).find("td").eq(index).find(".layui-table-cell").html()
                    }
                    if (cmpContent === initContent) {
                        theSameCount++;
                        if (i1 === data.length - 1) {
                            // 合并单元格
                            $row.eq(i1 - theSameCount + 1).find("td").eq(index).attr("rowspan", theSameCount);
                            for (var i2 = 1; i2 < theSameCount; i2++) { // 删除单元格
                                $row.eq(i1 - i2 + 1).find("td").eq(index).attr("del", "true")
                            }
                        }
                    } else {
                        // 合并单元格
                        $row.eq(i1 - theSameCount).find("td").eq(index).attr("rowspan", theSameCount);
                        for (var i3 = 1; i3 < theSameCount; i3++) { // 删除单元格
                            $row.eq(i1 - i3).find("td").eq(index).attr("del", "true")
                        }
                        theSameCount = 1;
                        initContent = cmpContent
                    }
                }
            }
        }
    };

    /**
     * 行鼠标右键
     * @param tableId 表格的id
     * @param callback 回调函数，不同的行生成不同的菜单；菜单数组
     * callback(d, tr): d表示行数据；tr表示行dom
     */
    tableX.bindCtxMenu = function (tableId, callback) {
        var data = table.cache[tableId];
        var ELEM_TR = "#" + tableId + "+.layui-table-view .layui-table-body tr";
        jquery(ELEM_TR).bind("contextmenu", function (event) {
            var $this = jquery(this);
            jquery(ELEM_TR).removeClass("layui-table-click");
            $this.addClass("layui-table-click");
            var menus;
            if (typeof callback === "function") {
                // 传入当前行的数据和DOM对象
                menus = callback(data[$this.data("index")], event.currentTarget)
            } else {
                menus = callback
            }

            function formatMenus(menus) {
                if (!menus) {
                    return
                }
                var configs = [];
                for (var i = 0; i < menus.length; i++) {
                    configs.push({
                        icon: menus[i].icon, name: menus[i].name, _click: menus[i].click, click: function (E, event) {
                            var $target = jquery(event.currentTarget);
                            this._click && this._click(data[$target.data("index")], event.currentTarget);
                            $target.removeClass("layui-table-click")
                        }, subs: formatMenus(menus[i].subs)
                    })
                }
                return configs
            }

            contextMenu.show(formatMenus(menus), event.clientX, event.clientY, event);
            return false
        })
    };

    /**
     * 导出数据excel
     * @param option
     * @returns {*}
     */
    tableX.exportData = function (option) {
        var w = option.cols;
        var J = option.data;
        var H = option.fileName;
        var r = option.expType;
        var y = option.option;
        y || (y = {});
        if (device.ie) {
            return layer.msg("不支持ie导出")
        }
        if (typeof J === "string") {
            var G = layer.load(2);
            y.url = J;
            tableX.loadUrl(y, function (L) {
                layer.close(G);
                option.data = L;
                tableX.exportData(option)
            });
            return
        }
        for (var F = 0; F < w.length; F++) {
            for (var E = 0; E < w[F].length; E++) {
                if (w[F][E].type === undefined) {
                    w[F][E].type = "normal"
                }
                if (w[F][E].hide === undefined) {
                    w[F][E].hide = false
                }
            }
        }
        var K = [], A = [], z = [];
        table.eachCols(undefined, function (L, M) {
            if (M.type === "normal" && !M.hide) {
                K.push(M.title || "");
                A.push(M.field || (m + L))
            }
        }, w);
        var I = tableX.parseTbData(w, tableX.deepClone(J), true);
        for (var B = 0; B < I.length; B++) {
            var u = [];
            for (var C = 0; C < A.length; C++) {
                var x = I[B][A[C]];
                x && (x = x.toString().replace(/,/g, "，"));
                u.push(x)
            }
            z.push(u.join(","))
        }
        var t = document.createElement("a");
        var s = ({csv: "text/csv", xls: "application/vnd.ms-excel"})[r || "xls"];
        var D = encodeURIComponent(K.join(",") + "\r\n" + z.join("\r\n"));
        t.href = "data:" + s + ";charset=utf-8,\ufeff" + D;
        t.download = (H || "table") + "." + (r || "xls");
        document.body.appendChild(t);
        t.click();
        document.body.removeChild(t)
    };

    /**
     * exportDataX方法使用的是社区excel模块导出的，是真正的xls格式，exportData以及layui自带的导出都是假的xls格式，
     * 如果数字前面有0会自动去掉0，exportDataX可解决此问题。
     * @param option
     */
    tableX.exportDataX = function (option) {
        layui.use("excel", function () {
            var A = layui.excel;
            var D = option.cols;
            var v = option.data;
            var t = option.fileName;
            var E = option.expType;
            var x = option.option;
            x || (x = {});
            E || (E = "xlsx");
            if (v && typeof v === "string") {
                var u = layer.load(2);
                x.url = v;
                tableX.loadUrl(x, function (F) {
                    layer.close(u);
                    option.data = F;
                    tableX.exportDataX(option)
                });
                return
            }
            for (var w = 0; w < D.length; w++) {
                for (var s = 0; s < D[w].length; s++) {
                    if (D[w][s].type === undefined) {
                        D[w][s].type = "normal"
                    }
                    if (D[w][s].hide === undefined) {
                        D[w][s].hide = false
                    }
                }
            }
            var z = {}, y = [];
            table.eachCols(undefined, function (F, G) {
                if (G.type === "normal" && !G.hide) {
                    var H = G.field || (m + F);
                    y.push(H);
                    z[H] = G.title || ""
                }
            }, D);
            var B = tableX.parseTbData(D, tableX.deepClone(v), true);
            var C = A.filterExportData(B, y);
            C.unshift(z);
            A.exportExcel({sheet1: C}, (t || "table") + "." + E, E)
        })
    };

    /**
     * 后端导出下载
     * @param url 后端的url
     * @param param 传递的参数
     * @param method 请求方式
     */
    tableX.exportDataBack = function (url, param, method) {
        param || (param = {});
        if (!method || method.toString().toLowerCase() === "get") {
            var v = "";
            for (var z in param) {
                if (!v) {
                    v = ("?" + z + "=" + param[z])
                } else {
                    v += ("&" + z + "=" + param[z])
                }
            }
            window.open(url + v)
        } else {
            var s = '<html><body><form id="eFrom" action="' + url + '" method="' + method + '">';
            for (var w in param) {
                s += ('<textarea name="' + w + '">' + param[w] + "</textarea>")
            }
            s += "</form></body></html>";
            jquery("#exportFrame").remove();
            jquery("body").append('<iframe id="exportFrame" style="display: none;"></iframe>');
            var A = document.getElementById("exportFrame");
            var y = A.contentWindow;
            var u = y.document;
            y.focus();
            u.open();
            u.write(s);
            u.close();
            u.getElementById("eFrom").submit()
        }
    };

    tableX.render = function (t) {
        var r = jquery(t.elem).attr("lay-filter");
        t.autoSort = false;
        var s = table.render(t);
        table.on("sort(" + r + ")", function (w) {
            var u = w.field, x = w.type;
            var v = jquery.extend(t.where, {sort: u, order: x});
            s.reload({where: v, page: {curr: 1}})
        });
        return s
    };

    /**
     * 前端分页排序
     * @param option
     * @returns {*}
     */
    tableX.renderFront = function (option) {
        var v, t = jquery(option.elem).attr("lay-filter");
        option.autoSort = false;
        for (var i = 0; i < option.cols.length; i++) {
            for (var j1 = 0; j1 < option.cols[i].length; j1++) {
                if (option.cols[i][j1].templet && !option.cols[i][j1].field) {
                    option.cols[i][j1].field = m + i + "_" + j1
                }
            }
        }
        if (option.url) {
            var u = tableX.deepClone(option);
            u.data = [];
            u.url = undefined;
            v = table.render(u);
            v.reloadUrl = function (y) {
                var x = tableX.deepClone(option);
                y && (x = jquery.extend(x, y));
                jquery(option.elem + "+.layui-table-view>.layui-table-box").append('<div class="layui-table-init"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>');
                tableX.loadUrl(x, function (z) {
                    v.reload({url: "", data: z, page: {curr: 1}});
                    tableX.putTbData(t, tableX.parseTbData(x.cols, z));
                    jquery("input[" + ELEM_SEARCH + '="' + t + '"]').val("");
                    window.tbX.cacheSearch[t] = undefined
                })
            };
            v.reloadUrl()
        } else {
            v = table.render(option);
            v.reloadData = function (x) {
                v.reload(x);
                tableX.parseTbData(option.cols, x.data);
                tableX.putTbData(t, x.data);
                jquery("input[" + ELEM_SEARCH + '="' + t + '"]').val("");
                window.tbX.cacheSearch[t] = undefined
            };
            tableX.putTbData(t, tableX.parseTbData(option.cols, option.data))
        }
        tableX.renderAllTool(v);
        return v
    };

    tableX.loadUrl = function (t, u) {
        t.response = jquery.extend({
            statusName: "code",
            statusCode: 0,
            msgName: "msg",
            dataName: "data",
            countName: "count"
        }, t.response);
        var r = t.response;
        var s = t.where;
        if (t.contentType && t.contentType.indexOf("application/json") === 0) {
            s = JSON.stringify(s)
        }
        jquery.ajax({
            type: t.method || "get",
            url: t.url,
            contentType: t.contentType,
            data: s,
            dataType: "json",
            headers: t.headers || {},
            success: function (v) {
                if (typeof t.parseData === "function") {
                    v = t.parseData(v) || v
                }
                if (v[r.statusName] != r.statusCode) {
                    var w = v[r.msgName] || ("返回的数据不符合规范，正确的成功状态码 (" + r.statusName + ") 应为：" + r.statusCode);
                    layer.msg(w, {icon: 2})
                } else {
                    u(v[r.dataName])
                }
            },
            error: function (w, v) {
                layer.msg("数据接口请求异常：" + v, {icon: 2})
            }
        })
    };

    tableX.parseTbData = function (x, u, s) {
        var w = [];
        table.eachCols(undefined, function (A, B) {
            if (B.templet) {
                var z = {field: ((B.field && (s || B.field.indexOf(m) === 0)) ? B.field : ("txField_" + A))};
                if (typeof B.templet === "string") {
                    z.templet = function (D) {
                        var C = undefined;
                        laytpl(jquery(B.templet).html()).render(D, function (E) {
                            C = E
                        });
                        return C
                    }
                } else {
                    z.templet = B.templet
                }
                w.push(z)
            }
        }, x);
        for (var t = 0; t < u.length; t++) {
            var v = u[t];
            for (var r = 0; r < w.length; r++) {
                var y = "<div>" + w[r].templet(v) + "</div>";
                v[w[r].field] = jquery(y).not(".export-hide").text().replace(/(^\s*)|(\s*$)/g, "")
            }
        }
        return u
    };

    tableX.putTbData = function (s, r) {
        window.tbX.cache[s] = r
    };

    tableX.getTbData = function (s) {
        var r = window.tbX.cache[s];
        return tableX.deepClone(r || table.cache[s])
    };

    tableX.filterData = function (z, s, r) {
        var t = [], x;
        for (var w = 0; w < z.length; w++) {
            var v = z[w];
            if (!x) {
                if (!s) {
                    x = [];
                    for (var y in v) {
                        if (!v.hasOwnProperty(y)) {
                            continue
                        }
                        x.push(y)
                    }
                } else {
                    x = s.split(",")
                }
            }
            for (var u = 0; u < x.length; u++) {
                if (tableX.isContains(v[x[u]], r)) {
                    t.push(v);
                    break
                }
            }
        }
        return t
    };

    tableX.isContains = function (s, r) {
        s || (s = "");
        r || (r = "");
        s = s.toString().toLowerCase();
        r = r.toString().toLowerCase();
        if (s === r || s.indexOf(r) >= 0) {
            return true
        }
        return false
    };

    tableX.renderAllTool = function (r) {
        o(r);
        l(r);
        j(r);
        k(r)
    };

    tableX.deepClone = function (u) {
        var r;
        var s = tableX.isClass(u);
        if (s === "Object") {
            r = {}
        } else {
            if (s === "Array") {
                r = []
            } else {
                return u
            }
        }
        for (var t in u) {
            if (!u.hasOwnProperty(t)) {
                continue
            }
            var v = u[t];
            if (tableX.isClass(v) === "Object") {
                r[t] = arguments.callee(v)
            } else {
                if (tableX.isClass(v) === "Array") {
                    r[t] = arguments.callee(v)
                } else {
                    r[t] = u[t]
                }
            }
        }
        return r
    };

    tableX.isClass = function (r) {
        if (r === null) {
            return "Null"
        }
        if (r === undefined) {
            return "Undefined"
        }
        return Object.prototype.toString.call(r).slice(8, -1)
    };

    window.tbX || (window.tbX = {});
    window.tbX.cache || (window.tbX.cache = {});
    window.tbX.cacheSearch || (window.tbX.cacheSearch = {});

    var j = function (s) {
        var r = s.config.id, t = jquery("input[" + ELEM_SEARCH + '="' + r + '"]');
        if (!(t && t.length > 0)) {
            return
        }
        if (!t.attr("placeholder")) {
            t.attr("placeholder", "输入关键字按回车键搜索")
        }
        t.off("keydown").on("keydown", function (x) {
            if (x.keyCode !== 13) {
                return
            }
            var u = t.attr("name");
            var y = t.val().replace(/(^\s*)|(\s*$)/g, "");
            var v = layer.msg("搜索中..", {icon: 16, shade: 0.01, time: 0});
            var w = tableX.getTbData(r);
            var z = tableX.filterData(w, u, y);
            window.tbX.cacheSearch[r] = z;
            s.reload({url: "", data: z, page: {curr: 1}});
            layer.close(v)
        })
    };

    var l = function (s) {
        var r = s.config.id;
        table.on("sort(" + r + ")", function (w) {
            var t = w.field, x = w.type;
            var u = layer.msg("加载中..", {icon: 16, shade: 0.01, time: 0});
            var v = window.tbX.cacheSearch[r];
            v || (v = tableX.getTbData(r));
            if (x) {
                v = v.sort(function (B, z) {
                    var A = B[t], y = z[t];
                    if (x === "asc") {
                        return (A === y) ? 0 : ((A < y) ? -1 : 1)
                    } else {
                        return (A === y) ? 0 : ((A < y) ? 1 : -1)
                    }
                })
            }
            s.reload({initSort: w, url: "", data: v, page: {curr: 1}});
            layer.close(u)
        })
    };

    var o = function (r) {
        jquery("[" + ELEM_REFRESH + '="' + r.config.id + '"]').off("click").on("click", function () {
            if (r.reloadUrl) {
                r.reloadUrl()
            } else {
                r.reload({page: {curr: 1}})
            }
        })
    };

    var k = function (s) {
        var r = s.config.id;
        jquery("[" + ELEM_EXPORT + '="' + r + '"]').off("click").on("click", function (t) {
            if (jquery(this).find(".tbx-dropdown-menu").length > 0) {
                return
            }
            if (t !== void 0) {
                t.preventDefault();
                t.stopPropagation()
            }
            var u = '<div class="tbx-dropdown-menu">';
            u += '      <div class="tbx-dropdown-menu-item" data-type="check">导出选中数据</div>';
            u += '      <div class="tbx-dropdown-menu-item" data-type="current">导出当前页数据</div>';
            u += '      <div class="tbx-dropdown-menu-item" data-type="all">导出全部数据</div>';
            u += "   </div>";
            jquery(this).append(u);
            jquery(this).addClass("tbx-dropdown-btn");
            jquery(this).parent().css("position", "relative");
            jquery(this).parent().css("z-index", "9998");
            jquery(".tbx-dropdown-menu").off("click").on("click", ".tbx-dropdown-menu-item", function (x) {
                var w = jquery(this).data("type");
                if (w === "check") {
                    var v = table.checkStatus(r);
                    if (v.data.length === 0) {
                        layer.msg("请选择要导出的数据", {icon: 2})
                    } else {
                        jquery(".tbx-dropdown-menu").remove();
                        tableX.exportData({fileName: s.config.title, cols: s.config.cols, data: v.data})
                    }
                } else {
                    if (w === "current") {
                        tableX.exportData({fileName: s.config.title, cols: s.config.cols, data: table.cache[r]})
                    } else {
                        if (w === "all") {
                            tableX.exportData({fileName: s.config.title, cols: s.config.cols, data: tableX.getTbData(r)})
                        }
                    }
                }
                if (x !== void 0) {
                    x.preventDefault();
                    x.stopPropagation()
                }
            })
        });
        jquery(document).off("click.tbxDropHide").on("click.tbxDropHide", function () {
            jquery(".tbx-dropdown-menu").remove()
        })
    };

    var d = function () {
        var r = ".tbx-dropdown-btn {";
        r += "        position: relative;";
        r += "   }";
        r += "   .tbx-dropdown-btn:hover {";
        r += "        opacity: 1";
        r += "   }";
        r += "   .tbx-dropdown-menu {";
        r += "        position: absolute;";
        r += "        top: 100%;";
        r += "        right: 0;";
        r += "        padding: 5px 0;";
        r += "        margin: 5px 0 0 0;";
        r += "        overflow: visible;";
        r += "        min-width: 110px;";
        r += "        background: #fff;";
        r += "        border-radius: 2px;";
        r += "        box-shadow: 0 2px 4px rgba(0, 0, 0, .12);";
        r += "        border: 1px solid #d2d2d2;";
        r += "        z-index: 9998;";
        r += "        cursor: default;";
        r += "   }";
        r += "   .tbx-dropdown-menu .tbx-dropdown-menu-item {";
        r += "        display: block;";
        r += "        color: #555;";
        r += "        font-size: 14px;";
        r += "        padding: 10px 15px;";
        r += "        text-decoration: none;";
        r += "        white-space: nowrap;";
        r += "        cursor: pointer;";
        r += "        user-select: none;";
        r += "        line-height: normal;";
        r += "   }";
        r += "   .tbx-dropdown-menu .tbx-dropdown-menu-item:hover {";
        r += "        background-color: #eeeeee;";
        r += "   }";
        r += "   .export-show {";
        r += "        display: none;";
        r += "   }";
        return r
    };

    jquery("head").append('<style id="ew-css-tbx" type="text/css">' + d() + "</style>");
    exports("tableX", tableX);
});